﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using OSGeo.MapGuide;
using System.IO;
using System.Configuration;
using System.Xml;
using System.Collections.Specialized;

namespace NegevGas.Core
{
    public class HtzMgHelper
    {
        // Fields
       private LayoutModulesConfiguration _config;
        private MgSiteConnection _connection;
        private MgFeatureService _featureService;
        private readonly string _layoutId;
        private MgMap _map;
        private readonly string _mapName;
        private MgResourceService _resourceService;
        private MgSelection _selection;
        private readonly string _sessionId;
       
        public string _projectname { get; set; }
        // Methods
        public HtzMgHelper(string sessionId, string mapName, string layoutId)
        {
            Init();
            this._sessionId = sessionId;
            this._mapName = mapName;
            this._layoutId = layoutId;
        }
       
        
        

        public HtzMgHelper(string userName, string userPass, string layoutId, string mapDefinition)
        {
            Init();
            this._connection = new MgSiteConnection();
            this._connection.Open(new MgUserInformation(userName, userPass));
            this._sessionId = this._connection.GetSite().CreateSession();
            this._map = new MgMap();
            MgResourceIdentifier mapDef = new MgResourceIdentifier(mapDefinition);
            this._map.Create(this.ResourceService, mapDef, mapDef.Name);
            this._layoutId = layoutId;
        }

        ~HtzMgHelper()
        {
            if (this._connection != null)
            {
                this._connection.Dispose();
            }
            if (this._featureService != null)
            {
                this._featureService.Dispose();
            }
            if (this._resourceService != null)
            {
                this._resourceService.Dispose();
            }
            if (this._map != null)
            {
                this._map.Dispose();
            }
        }

        public string GetDefaultGeometryPropertyName(MgLayer layer)
        {
            return this.FeatureService.GetClassDefinition(new MgResourceIdentifier(layer.FeatureSourceId), layer.FeatureClassName.Split(new char[] { ':' })[0], layer.FeatureClassName.Split(new char[] { ':' })[1]).GetDefaultGeometryPropertyName();
        }

        public object GetFeaturePropertyValue(MgReader reader, string propertyName)
        {
            return this.GetFeaturePropertyValue(reader, propertyName, false);
        }

        public object GetFeaturePropertyValue(MgReader reader, string propertyName, bool toString)
        {
            object val = null;

       
            int propertyType = reader.GetPropertyType(propertyName);
            if (reader.IsNull(propertyName))
            {
                switch (propertyType)
                {
                    case 9:
                        val = string.Empty;
                        break;

                    case 3:
                        if (toString)
                        {
                            val = string.Empty;
                        }
                        else
                        {
                            val = new DateTime();
                        }
                        break;
                }
            }
            else
            {
                switch (propertyType)
                {
                    case 1:
                        val = reader.GetBoolean(propertyName);
                        goto Label_01BE;

                    case 2:
                        val = reader.GetByte(propertyName);
                        goto Label_01BE;

                    case 3:
                        {
                            MgDateTime dt = reader.GetDateTime(propertyName);
                            if (!toString)
                            {
                                val = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second);
                            }
                            else
                            {
                                string strDt = string.Empty;
                                if (dt != null)
                                {
                                    strDt = string.Format("{0}/{1}/{2}", dt.Day, dt.Month, dt.Year);
                                }
                                val = strDt;
                            }
                            goto Label_01BE;
                        }
                    case 4:
                        val = Math.Round((double)reader.GetSingle(propertyName), 2);
                        goto Label_01BE;

                    case 5:
                        val = Math.Round(reader.GetDouble(propertyName), 2);
                        goto Label_01BE;

                    case 6:
                        val = reader.GetInt16(propertyName);
                        goto Label_01BE;

                    case 7:
                        val = reader.GetInt32(propertyName);
                        goto Label_01BE;

                    case 8:
                        val = reader.GetInt64(propertyName);
                        goto Label_01BE;

                    case 9:
                        val = reader.GetString(propertyName);
                        goto Label_01BE;
                }
            }
        Label_01BE:
            if (toString && (val == null))
            {
                val = string.Empty;
            }
            return val;
        }

        public Dictionary<string, string> GetLayerList()
        {
            return this.GetLayerList(false);
        }

        public Dictionary<string, string> GetLayerList(bool selectableOnly)
        {
            MgLayerCollection layers = this.Map.GetLayers();
            if (layers == null)
            {
                return null;
            }
            Dictionary<string, string> items = new Dictionary<string, string>();
            foreach (MgLayerBase layer in layers)
            {
                if (!selectableOnly || ((!layer.Name.StartsWith("_") && !layer.FeatureSourceId.ToUpper().StartsWith("SESSION")) && layer.Selectable))
                {
                    string layerName = layer.Name;
                    string layerDisplayName = string.Empty;
                    if (layer.Group != null)
                    {
                        layerDisplayName = layerDisplayName + layer.Group.LegendLabel + " - ";
                    }
                    layerDisplayName = layerDisplayName + layer.LegendLabel;
                    items.Add(layerName, layerDisplayName);
                }
            }
            return items;
        }

        public Dictionary<string, string> GetMinMax(MgLayerBase layer, string propertyName)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();
            object min = null;
            object max = null;
            MgFeatureAggregateOptions opt = new MgFeatureAggregateOptions();
            opt.AddComputedProperty("MIN", string.Format("Min({0})", propertyName));
            opt.AddComputedProperty("MAX", string.Format("Max({0})", propertyName));
            MgDataReader reader = this.FeatureService.SelectAggregate(new MgResourceIdentifier(layer.FeatureSourceId), layer.FeatureClassName, opt);
            if (reader.ReadNext())
            {
                min = this.GetFeaturePropertyValue(reader, "MIN");
                max = this.GetFeaturePropertyValue(reader, "MAX");
            }
            if (min != null)
            {
                result.Add("min", min.ToString());
            }
            if (max != null)
            {
                result.Add("max", max.ToString());
            }
            return result;
        }

        public Dictionary<string, string> GetPropertiesList(MgLayer layer)
        {
            Dictionary<string, string> properties = new Dictionary<string, string>();
            MgByteReader reader = this.ResourceService.GetResourceContent(layer.LayerDefinition);
            string xmlSchema = reader.ToString();
            reader.Dispose();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(xmlSchema);
            XmlNodeList xmlProperties = xmlDoc.GetElementsByTagName("PropertyMapping");
            foreach (XmlNode node in xmlProperties)
            {
                string name = node.SelectSingleNode("Name").InnerText;
                string alias = node.SelectSingleNode("Value").InnerText;
                properties.Add(name, alias);
            }
            return properties;
        }

        public Dictionary<string, string> GetPropertiesList(string layerName)
        {
            MgLayer layer = (MgLayer)this.Map.GetLayers().GetItem(layerName);
            return this.GetPropertiesList(layer);
        }

        public string GetSdfFile(string featureSourceId)
        {
            string fileName = string.Empty;
            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["XmlDataFolder"]))
            {
                string xmlFile = Path.Combine(HttpContext.Current.Server.MapPath(string.Format("~/{0}", ConfigurationManager.AppSettings["XmlDataFolder"])), "SDF_Files.xml");
                if (!File.Exists(xmlFile))
                {
                    return fileName;
                }
                XmlDocument doc = new XmlDocument();
                doc.Load(xmlFile);
                XmlNode node = doc.SelectSingleNode(string.Format("/root/FeatureSource[@ID=\"{0}\"]", featureSourceId));
                if (node != null)
                {
                    fileName = node.Attributes["file"].InnerText;
                }
            }
            return fileName;
        }

        public Dictionary<string, string> GetSelectedLayers(MgSelection selection, bool addGroupName)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();
            foreach (MgLayerBase l in selection.GetLayers())
            {
                string label = l.LegendLabel;
                if (addGroupName)
                {
                    for (MgLayerGroup group = l.Group; group != null; group = group.Group)
                    {
                        label = string.Format("{0} - {1}", group.LegendLabel, label);
                    }
                }
                result.Add(l.Name, label);
            }
            return result;
        }

        public Dictionary<string, string> GetSelectedLayers(string selectionXml, bool addGroupName)
        {
            MgSelection sel = new MgSelection(this.Map, selectionXml);
            return this.GetSelectedLayers(sel, addGroupName);
        }

        public object GetValueByForeignKey(MgLayer layer, string propertyName, object value)
        {
            string schemaName = layer.FeatureClassName.Split(new char[] { ':' })[0];
            string className = propertyName.Split(new char[] { '_' })[1];
            MgResourceIdentifier resourceId = new MgResourceIdentifier(layer.FeatureSourceId);
            if (this.FeatureService.GetClasses(resourceId, schemaName).Contains(string.Format("{0}:{1}", schemaName, className)))
            {
                MgClassDefinition classDefinition = this.FeatureService.GetClassDefinition(resourceId, schemaName, className);
                MgPropertyDefinitionCollection properties = classDefinition.GetProperties();
                MgDataPropertyDefinition keyProperty = classDefinition.GetIdentityProperties()[0] as MgDataPropertyDefinition;
                MgDataPropertyDefinition valProperty = null;
                foreach (MgDataPropertyDefinition dpd in properties.OfType<MgDataPropertyDefinition>())
                {
                    if (dpd.Name.Equals("code", StringComparison.InvariantCultureIgnoreCase))
                    {
                        keyProperty = dpd;
                    }
                    else if (dpd.DataType == 9)
                    {
                        valProperty = dpd;
                    }
                }
                if ((keyProperty != null) && (valProperty != null))
                {
                    MgFeatureQueryOptions opt = new MgFeatureQueryOptions();
                    opt.SetFilter(string.Format("{0}={1}", keyProperty.Name, value));
                    MgFeatureReader reader = this.FeatureService.SelectFeatures(resourceId, string.Format("{0}:{1}", schemaName, className), opt);
                    if (reader.ReadNext())
                    {
                        value = this.GetFeaturePropertyValue(reader, valProperty.Name);
                    }
                }
            }
            return value;
        }

        private static void Init()
        {
            MapGuideApi.MgInitializeWebTier(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "webconfig.ini"));
        }

        public bool PropertyIsString(MgLayer layer, string propertyName)
        {
            MgDataPropertyDefinition streetCode1Property = this.FeatureService.GetClassDefinition(new MgResourceIdentifier(layer.FeatureSourceId), layer.FeatureClassName.Split(new char[] { ':' })[0], layer.FeatureClassName.Split(new char[] { ':' })[1]).GetProperties().GetItem(propertyName) as MgDataPropertyDefinition;
            return (streetCode1Property.DataType == 9);
        }

        public string SelectFeatureOnMap(string layerName, int id)
        {
            return this.SelectFeaturesOnMap(layerName, new string[] { id.ToString() });
        }

        public string SelectFeaturesOnMap(string layerName, string[] ids)
        {
            string result = string.Empty;
            if (this.Map.GetLayers().Contains(layerName))
            {
                MgLayer layer = this.Map.GetLayers().GetItem(layerName) as MgLayer;
                MgFeatureQueryOptions opt = new MgFeatureQueryOptions();
                string identityName = this.FeatureService.GetClassDefinition(new MgResourceIdentifier(layer.FeatureSourceId), layer.FeatureClassName.Split(new char[] { ':' })[0], layer.FeatureClassName.Split(new char[] { ':'})[1]).GetIdentityProperties()[0].Name;
                opt.SetFilter(string.Format("{0} in({1})", identityName, ids.ToString()));
                MgFeatureReader reader = this.FeatureService.SelectFeatures(new MgResourceIdentifier(layer.FeatureSourceId), layer.FeatureClassName, opt);
                MgSelection selection = new MgSelection(this.Map);
                selection.AddFeatures(layer, reader, ids.Length);
                result = selection.ToXml();
            }
            return result;
        }
        public NameValueCollection GetRequestParameters()
        {
            if ("POST" == HttpContext.Current.Request.HttpMethod)
            {
                return HttpContext.Current.Request.Form;
            }
            else
            {
                return HttpContext.Current.Request.QueryString;
            }
        }
        // Properties
        public LayoutModulesConfiguration Configuration
        {
            get
            {
                if (!((this._config != null) || string.IsNullOrEmpty(this._layoutId)))
                {
                    this._config = new LayoutModulesConfiguration(this._layoutId);
                }
                return this._config;
            }
        }

        public MgSiteConnection Connection
        {
            get
            {
                if (this._connection == null)
                {
                    this._connection = new MgSiteConnection();
                    try
                    {
                        this._connection.Open(new MgUserInformation(this._sessionId));
                    }
                    catch (MgSessionExpiredException)
                    {
                        this._connection.Open(new MgUserInformation(ConfigurationManager.AppSettings["MgUser"], ConfigurationManager.AppSettings["MgPass"]));
                    }
                }
                return this._connection;
            }
        }

        public MgFeatureService FeatureService
        {
            get
            {
                return (this._featureService ?? (this._featureService = this.Connection.CreateService(2) as MgFeatureService));
            }
        }

        public MgMap Map
        {
            get
            {
                if (this._map == null)
                {
                    this._map = new MgMap();
                    this._map.Open(this.ResourceService, this._mapName);
                }
                return this._map;
            }
        }

        public MgResourceService ResourceService
        {
            get
            {
                return (this._resourceService ?? (this._resourceService = this.Connection.CreateService(0) as MgResourceService));
            }
        }

        public MgSelection Selection
        {
            get
            {
                if (this._selection == null)
                {
                    this._selection = new MgSelection(this.Map);
                    this._selection.Open(this.ResourceService, this.Map.Name);
                }
                return this._selection;
            }
            set
            {
                this._selection = value;
            }
        }

        public string SessionId
        {
            get
            {
                return this._sessionId;
            }
        }
    }


}